package cn.migu.music.hangupsms.service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import com.alibaba.fastjson.JSON;

import cn.migu.music.common.exception.BusinessException;
import cn.migu.music.common.utils.LogUtils;
import cn.migu.music.hangupsms.cachemanage.LocalCacheManager;
import cn.migu.music.hangupsms.cachemanage.event.EventConstants;
import cn.migu.music.hangupsms.common.entity.*;
import cn.migu.music.hangupsms.repository.SmsSendTimeSettingsMapper;
import lombok.extern.slf4j.Slf4j;

@RestController
@Slf4j
public class SmsSendTimeSettingsService implements SettingsApplyHandler {
    private static final String       TX_PREFIX = "smsTime";
    private static final String       OP_TABLE  = "t_migu_hangup_sms_send_time";
    @Autowired
    private SmsSendTimeSettingsMapper smsSendTimeSettingsMapper;
    @Autowired
    private SettingsChangeLogService  changeLogService;
    @Autowired
    private LocalCacheManager         cacheManager;

    @PostConstruct
    public void init() {
        changeLogService.registerApply(TX_PREFIX, this);
    }

    /**
     * 新增发送时间限制配置
     * 
     * @param smsTimeOperation
     * @return
     */
    @Transactional
    @PostMapping("/hangupsms/settings/sms-time/add/v1.0")
    public SettingResponse<String> addSmsSendTimeSettings(@RequestBody SmsTimeOperation smsTimeOperation) {
        SettingResponse<String> response = new SettingResponse<>();
        if (isParamInvalidate(response, smsTimeOperation)) {
            return response;
        }
        SmsSendTimeSettings timeSettings = new SmsSendTimeSettings();
        timeSettings.setProvinceId(smsTimeOperation.getProvinceId());
        timeSettings.setDayStartTime(smsTimeOperation.getDayStartTime());
        timeSettings.setDayEndTime(smsTimeOperation.getDayEndTime());
        timeSettings.setElapsedMaxTime(smsTimeOperation.getElapsedMaxTime());
        timeSettings.setChangeTime(LocalDateTime.now());
        timeSettings.setApplyStatus(0);
        try {
            insertToDb(timeSettings, smsTimeOperation);
        } catch (Exception e) {
            LogUtils.error(e, log, "save db error");
            response.setResultCode(SettingResponse.ERROR_CODE);
            response.setResultMessage(e.getMessage());
            return response;
        }
        response.setResultCode(SettingResponse.SUCCESS_CODE);
        response.setResultMessage(SettingResponse.SUCCESS_MSG);
        String txId = TX_PREFIX + "." + timeSettings.getProvinceId();
        response.setData(txId);
        return response;
    }

    @Transactional
    public void insertToDb(SmsSendTimeSettings timeSettings, SmsTimeOperation smsTimeOperation) {
        SmsSendTimeSettings timeSettingsOld = smsSendTimeSettingsMapper.getIgnoreDelete(smsTimeOperation.getProvinceId());
        if (timeSettingsOld == null) {
            smsSendTimeSettingsMapper.add(timeSettings);
        } else if (timeSettingsOld.getDeleteFlag() == 1) {
            timeSettings.setDeleteFlag(0);
            smsSendTimeSettingsMapper.updateTime(timeSettings);
        } else {
            throw BusinessException.newInstance("data exists!");
        }
        smsTimeOperation.setOperationEnum(SettingOperationEnum.ADD);
        changeLogService.addLog(smsTimeOperation, OP_TABLE, timeSettings.getProvinceId(), JSON.toJSONString(timeSettings), "");
    }

    private boolean isParamInvalidate(SettingResponse<String> response, SmsTimeOperation smsTimeOperation) {
        response.setResultCode(SettingResponse.ERROR_CODE);
        if (StringUtils.isEmpty(smsTimeOperation.getProvinceId())) {
            response.setResultMessage("province id is empty");
            return true;
        }
        if (StringUtils.isEmpty(smsTimeOperation.getDayStartTime()) &&
            StringUtils.isEmpty(smsTimeOperation.getDayEndTime()) &&
            smsTimeOperation.getElapsedMaxTime() == null) {
            response.setResultMessage("all time attributes is empty");
            return true;
        }
        if (smsTimeOperation.getElapsedMaxTime() != null && smsTimeOperation.getElapsedMaxTime() < 0) {
            response.setResultMessage("negative time attribute");
            return true;
        }
        if (StringUtils.isNotEmpty(smsTimeOperation.getDayStartTime()) && StringUtils.isNotEmpty(smsTimeOperation.getDayEndTime())) {
            int cr = StringUtils.compare(smsTimeOperation.getDayEndTime(), smsTimeOperation.getDayStartTime());
            if (cr <= 0) {
                response.setResultMessage("invalid time interval");
                return true;
            }
        }
        response.setResultCode(SettingResponse.SUCCESS_CODE);
        return false;
    }

    /**
     * 修改发送时间限制配置
     * 
     * @param smsTimeOperation
     * @return
     */
    @Transactional
    @PostMapping("/hangupsms/settings/sms-time/edit/v1.0")
    public SettingResponse<String> updateSmsSendTimeSettings(@RequestBody SmsTimeOperation smsTimeOperation) {
        SettingResponse<String> response = new SettingResponse<>();
        if (isParamInvalidate(response, smsTimeOperation)) {
            response.setResultCode(SettingResponse.ERROR_CODE);
            return response;
        }
        SmsSendTimeSettings timeSettingsOld = smsSendTimeSettingsMapper.get(smsTimeOperation.getProvinceId());
        if (timeSettingsOld == null) {
            response.setResultCode(SettingResponse.ERROR_CODE);
            response.setResultMessage("no settings for province:" + smsTimeOperation.getProvinceId());
            return response;
        }
        SmsSendTimeSettings timeSettings = new SmsSendTimeSettings();
        timeSettings.setProvinceId(smsTimeOperation.getProvinceId());
        timeSettings.setDayStartTime(smsTimeOperation.getDayStartTime());
        timeSettings.setDayEndTime(smsTimeOperation.getDayEndTime());
        timeSettings.setElapsedMaxTime(smsTimeOperation.getElapsedMaxTime());
        timeSettings.setChangeTime(LocalDateTime.now());
        timeSettings.setApplyStatus(0);
        try {
            updateDb(timeSettings, smsTimeOperation, timeSettingsOld);
        } catch (Exception e) {
            LogUtils.error(e, log, "save db error");
            response.setResultCode(SettingResponse.ERROR_CODE);
            response.setResultMessage(e.getMessage());
            return response;
        }
        response.setResultCode(SettingResponse.SUCCESS_CODE);
        response.setResultMessage(SettingResponse.SUCCESS_MSG);
        String txId = TX_PREFIX + "." + timeSettings.getProvinceId();
        response.setData(txId);
        return response;
    }

    @Transactional
    public void updateDb(SmsSendTimeSettings timeSettings, SmsTimeOperation smsTimeOperation, SmsSendTimeSettings timeSettingsOld) {
        smsSendTimeSettingsMapper.updateTime(timeSettings);
        smsTimeOperation.setOperationEnum(SettingOperationEnum.EDIT);
        changeLogService.addLog(smsTimeOperation, OP_TABLE, timeSettings.getProvinceId(), JSON.toJSONString(timeSettings),
            JSON.toJSONString(timeSettingsOld));
    }

    /**
     * 查询发送时间限制配置
     * 
     * @param provinceId
     *            省编码
     * @return
     */
    @GetMapping("/hangupsms/settings/sms-time/display/v1.0")
    public SettingResponse<List<SmsSendTimeSettings>> getSmsSendTimeSettings(@RequestParam String provinceId) {
        SettingResponse<List<SmsSendTimeSettings>> response = new SettingResponse<>();
        if (StringUtils.isEmpty(provinceId)) {
            List<SmsSendTimeSettings> settingsList = smsSendTimeSettingsMapper.getAllSettings();
            response.setData(settingsList);
        } else {
            List<SmsSendTimeSettings> settingsList = new ArrayList<>(1);
            SmsSendTimeSettings settings = smsSendTimeSettingsMapper.get(provinceId);
            if (settings != null) {
                settingsList.add(settings);
            }
            response.setData(settingsList);
        }
        response.setResultCode(SettingResponse.SUCCESS_CODE);
        return response;
    }

    /**
     * 删除发送时间限制配置
     * 
     * @param smsTimeOperation
     * @return
     */
    @Transactional
    @PostMapping("/hangupsms/settings/sms-time/delete/v1.0")
    public SettingResponse<String> deleteSmsSendTimeSettings(@RequestBody SmsTimeOperation smsTimeOperation) {
        SettingResponse<String> response = new SettingResponse<>();
        String provinceId = smsTimeOperation.getProvinceId();
        if (StringUtils.isEmpty(provinceId) || StringUtils.equals("default", provinceId)) {
            response.setResultMessage("invalid province id");
            response.setResultCode(SettingResponse.ERROR_CODE);
            return response;
        } else {
            SmsSendTimeSettings settings = smsSendTimeSettingsMapper.get(provinceId);
            if (settings == null) {
                response.setResultCode(SettingResponse.ERROR_CODE);
                response.setResultMessage("data not exist!");
            } else {
                smsSendTimeSettingsMapper.delete(provinceId);
                SmsSendTimeSettings settingsDeleted = smsSendTimeSettingsMapper.getIgnoreDelete(provinceId);
                smsTimeOperation.setOperationEnum(SettingOperationEnum.DELETE);
                changeLogService.addLog(smsTimeOperation, OP_TABLE, provinceId, JSON.toJSONString(settings), JSON.toJSONString(settingsDeleted));
                response.setResultCode(SettingResponse.SUCCESS_CODE);
                response.setResultMessage(SettingResponse.SUCCESS_MSG);
                response.setData(TX_PREFIX + "." + provinceId);
            }
        }
        return response;
    }

    @Override
    public boolean apply(String rowId, String user) {
        SmsSendTimeSettings settings = smsSendTimeSettingsMapper.getIgnoreDelete(rowId);
        if (settings != null) {
            smsSendTimeSettingsMapper.updateApplyStatus(rowId, 1, LocalDateTime.now());
            SmsSendTimeSettings updatedSettings = smsSendTimeSettingsMapper.getIgnoreDelete(rowId);
            if (updatedSettings.getApplyStatus() != 1) {
                return false;
            }
            cacheManager.broadcastEvent(EventConstants.SMS_SEND_TIME_CHANGED_EVENT);
            OperateBase operateBase = new OperateBase();
            operateBase.setOperationEnum(SettingOperationEnum.APPLY);
            operateBase.setOperateUser(user);
            changeLogService.addLog(operateBase, OP_TABLE, settings.getProvinceId(), JSON.toJSONString(updatedSettings), JSON.toJSONString(settings));
            return true;
        }
        return false;
    }
}
